/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package op;

import in_out.IOUtils;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author Jonatas
 */
public class ContaTelefonica {

    public List<Telefone> getOrigens() {

        List<Telefone> origens = new ArrayList<Telefone>();

        for (Ligacao lig : ligacoes) {
            Telefone origem = lig.getNumeroDeOrigem();
            if (!origens.contains(origem)) {
                origens.add(origem);
            }
        }


        return origens;
    }

    public static ContaTelefonica createOiContaTotal(BufferedReader reader) throws Exception {
        ContaTelefonica contaTelefonica = new ContaTelefonica();

        contaTelefonica.contaMensal = new ArrayList<EntradaAbstrata>();
        String line = null;
        Telefone origem = null;
        String tipo = null;
        boolean aCobrar = false;
        boolean diversos = false;

        while ((line = reader.readLine()) != null) {

            line = line.trim();

            if (line.length() == 0) {
                continue;
            }

            {
                if (line.toLowerCase().startsWith("ligações usando")) {
                    tipo = line.trim();
                    aCobrar = false;
                    diversos = false;
                    continue;
                } else if (line.toLowerCase().startsWith("ligações de")) {
                    tipo = line.trim();
                    aCobrar = false;
                    diversos = false;
                    continue;
                } else if (line.toLowerCase().startsWith("ligações recebidas a cobrar")) {
                    tipo = line.trim();
                    aCobrar = true;
                    diversos = false;
                    continue;
                } else if (line.toLowerCase().startsWith("ligações que voce recebeu a cobrar")) {
                    tipo = line.trim();
                    aCobrar = true;
                    diversos = false;
                    continue;
                } else if (line.toLowerCase().startsWith("ligações que você recebeu em viagens nacionais")) {
                    tipo = line.trim();
                    aCobrar = false;
                    diversos = false;
                    continue;
                } else if (line.toLowerCase().startsWith("mensagens/internet móvel") || line.toLowerCase().startsWith("oi torpedo")
                        || line.toLowerCase().startsWith("oi dados") || line.toLowerCase().startsWith("oi serviços especiais")
                        || line.toLowerCase().startsWith("assinatura de conteúdos sms e downloads")) {
                    tipo = line.trim();
                    aCobrar = false;
                    diversos = false;
                    continue;
                } else if (line.toLowerCase().startsWith("outros serviços")) {
                    tipo = line.trim();
                    aCobrar = false;
                    diversos = false;
                    continue;
                } else if (line.toLowerCase().contains("diversos")) {
                    diversos = true;
                    continue;
                }
            }

            if (line.toLowerCase().contains("resumo do seu oi")) {

                Pattern p = Pattern.compile("[0-9]{2} [0-9]{4} [0-9]{4}");
                Matcher m = p.matcher(line);
                m.find();

                String[] tel = m.group().trim().split(" ");

                origem = new Telefone(tel[0], tel[1], tel[2]);

                while (!(line = reader.readLine()).contains("Total a pagar do seu Oi")) {
                    EntradaAbstrata entrada = QuebraStringOI.quebraStringPlanoOIContaTotal(origem, line);
                    if (entrada != null) {
                        contaTelefonica.contaMensal.add(entrada);
                    }
                }

                continue;

            }



            if (line.startsWith("Ligações originadas no fixo usando a Oi")) {

                Pattern p = Pattern.compile("[0-9]{2} [0-9]{4}[0-9]{4}");
                Matcher m = p.matcher(line);
                m.find();

                String tel = m.group().trim().replace(" ", "");
                origem = new Telefone("0" + tel);

                continue;

            }

            if (diversos) {
                continue;
            }

            if (origem == null) {
                continue;
            }

            int ocorrencias = 0;

            if (tipo.equals("Mensagens/Internet Móvel") || tipo.equals("Oi Torpedo") || tipo.equals("Oi Dados")
                    || tipo.equals("Oi Serviços Especiais") || tipo.equals("Assinatura de conteúdos SMS e Downloads")) {
                Matcher match = QuebraStringOI.tempo.matcher(line);
                while (match.find()) {
                    ocorrencias++;
                }
            }

            if (ocorrencias <= 1) {
                String num = line.split(" ")[0];
                Pattern p = Pattern.compile("[0-9]{10}");
                Matcher m = p.matcher(num);
                if (m.find()) {
                    contaTelefonica.contaMensal.add(QuebraStringOI.quebraStringOIContaTotal(line, origem, tipo, aCobrar));
                }
            } else {
                Matcher match = QuebraStringOI.valor.matcher(line);
                match.find();
                int fim = match.end();

                String s[] = new String[2];
                s[0] = line.substring(0, fim + 1).trim();
                s[1] = line.substring(fim + 1).trim();

                for (String str : s) {
                    String num = str.split(" ")[0];
                    Pattern p = Pattern.compile("[0-9]{10}");
                    Matcher m = p.matcher(num);
                    if (m.find()) {
                        contaTelefonica.contaMensal.add(QuebraStringOI.quebraStringOIContaTotal(str, origem, tipo, aCobrar));
                    }
                }

            }



        }

        reader.close();

        Collections.sort(contaTelefonica.contaMensal, new ComparatorEntradaAbstrataPorTelefone());

        contaTelefonica.contaResumida();

        return contaTelefonica;
    }
    protected List<EntradaAbstrata> contaMensal;
    protected List<LigacaoResumida> contaResumida;
    protected List<Ligacao> ligacoes;

    public ContaTelefonica(List<EntradaAbstrata> contaMensal) {
        this.contaMensal = contaMensal;

        Collections.sort(contaMensal, new ComparatorEntradaAbstrataPorTelefone());

        contaResumida();
    }

    public List<EntradaAbstrata> getContaMensal() {
        return contaMensal;
    }

    public void setContaMensal(List<EntradaAbstrata> contaMensal) {
        this.contaMensal = contaMensal;
        contaResumida();
    }

    public List<LigacaoResumida> getContaResumida() {
        return contaResumida;
    }

    public List<Ligacao> getLigacoes() {
        return ligacoes;
    }

    public void setLigacoes(List<Ligacao> ligacoes) {
        this.ligacoes = ligacoes;
    }

    public ContaTelefonica(BufferedReader reader) throws Exception {

        contaMensal = new ArrayList<EntradaAbstrata>();
        String line = null;

        while ((line = reader.readLine()) != null) {

            line = line.trim();

            if (line.length() == 0) {
                continue;
            }

            contaMensal.add(EntradaAbstrata.quebraString(line));

        }

        reader.close();

        Collections.sort(contaMensal, new ComparatorEntradaAbstrataPorTelefone());

        contaResumida();

    }

    public static ContaTelefonica createContaTIM(BufferedReader reader) throws Exception {

        ContaTelefonica contaTelefonica = new ContaTelefonica();

        Pattern patternValor = Pattern.compile("-?[0-9]+[,][0-9]{2}");

        contaTelefonica.contaMensal = new ArrayList<EntradaAbstrata>();
        String line = null;
        Telefone origem = null;
        String plano = null;

        boolean acesso = false;

        String[] fullFile = IOUtils.fileToStringArray(reader);

        for (int i = 0; i < fullFile.length; i++) {

            line = fullFile[i].trim();

            int pctg = (int) ((((double) i) / ((double) fullFile.length)) * 100);

            if (line.length() == 0) {
                continue;
            }

            if (line.startsWith("Detalhamento de Servi")) {
                String[] aux = line.split(" ");

                String fone = aux[aux.length - 1];

                aux = fone.split("-");

                origem = new Telefone(aux[0], aux[1], aux[2]);

                continue;
            }

            if (origem == null) {
                continue;
            }

            if (line.startsWith("Chamadas") || line.startsWith("TIM Torpedo")) {
                plano = line;
                continue;
            }

            if (plano == null) {
                continue;
            }

            String[] tokens = line.split(" ");

            if (tokens.length < 2) {
                continue;
            }

            Pattern numeros = Pattern.compile("\\d\\d");
            Matcher matchNumeros = numeros.matcher(tokens[0]);

            Matcher data = QuebraStringTIM.data.matcher(tokens[1]);

            boolean found = matchNumeros.find();

            if (found && data.find()) {
                line = line.replace("\t", " ");
                contaTelefonica.contaMensal.add(QuebraStringTIM.quebraStringTIM(line, origem, plano));
            } else if (line.contains("Total de Uso") && !line.contains("Acesso") && !acesso) {

                Telefone atual = origem;

                while (++i < fullFile.length && origem.equals(atual)) {

                    line = fullFile[i];

                    if ((line.contains("Total de Uso") && line.contains("Acesso"))) {
                        acesso = true;
                        break;
                    }

                    if (line.startsWith("Chamadas") || line.startsWith("TIM Torpedo")) {
                        plano = line;
                        break;
                    }

                    if (line.startsWith("Detalhamento de Servi")) {
                        String[] aux = line.split(" ");

                        String fone = aux[aux.length - 1];

                        aux = fone.split("-");

                        atual = new Telefone(aux[0], aux[1], aux[2]);

                        continue;

                    }

                    Matcher matchValor = patternValor.matcher(line);

                    if (matchValor.find()) {
                        EntradaAbstrata entrada = QuebraStringTIM.quebraStringTimPlano(line, origem, matchValor.group());

                        if (entrada != null) {
                            contaTelefonica.contaMensal.add(entrada);
                        }

                    }

                }

                if (!origem.equals(atual)) {
                    origem = atual;
                }

                i--;


            } else if (line.startsWith("TIM Wap Fast") || line.startsWith("TIM Connect Fast")
                    || line.matches("Servi.os de Sons") || line.startsWith("BlackBerry Professional - MB")
                    || line.startsWith("TIM VideoMensagem")) {

                String planoAtual = line;

                line = fullFile[++i].trim();

                while (!line.startsWith("Data")) {
                    line = fullFile[++i].trim();
                }

                boolean fim = false;

                while (!fim) {
                    line = fullFile[++i].trim();
                    Matcher matchValor = patternValor.matcher(line);
                    Matcher matchData = QuebraStringTIM.data.matcher(line);

                    boolean encontrouValor = matchValor.find();
                    boolean encontrouData = matchData.find();

                    if (encontrouValor) {
                        if (!encontrouData) {
                            EntradaAbstrata entrada = null;

                            String valor = matchValor.group();

                            while (matchValor.find()) {
                                valor = matchValor.group();
                            }

                            entrada = QuebraStringTIM.quebraStringTimOutrosPlanos(planoAtual, origem, valor);


                            if (entrada != null) {
                                contaTelefonica.contaMensal.add(entrada);
                            }

                            fim = true;
                        }
                    }
                }
            }

        }

        reader.close();

        Collections.sort(contaTelefonica.contaMensal, new ComparatorEntradaAbstrataPorTelefone());

        contaTelefonica.contaResumida();

        return contaTelefonica;

    }

    public static ContaTelefonica createContaOI(BufferedReader reader) throws Exception {

        ContaTelefonica contaTelefonica = new ContaTelefonica();

        contaTelefonica.contaMensal = new ArrayList<EntradaAbstrata>();
        String line = null;
        Telefone origem = null;

        while ((line = reader.readLine()) != null) {

            line = line.trim();

            if (line.length() == 0) {
                continue;
            }


            if (origem == null) {
                String[] tokens = line.split(";");
                String num1 = tokens[2].trim().substring(0, 4);
                String num2 = tokens[2].trim().substring(5);

                origem = new Telefone(tokens[0].trim(), num1, num2);
                continue;
            }

            if (line.startsWith("00")) {
                contaTelefonica.contaMensal.add(QuebraStringOI.quebraStringOI(line, origem));
            }

        }

        reader.close();

        Collections.sort(contaTelefonica.contaMensal, new ComparatorEntradaAbstrataPorTelefone());

        contaTelefonica.contaResumida();


        return contaTelefonica;
    }

    public static ContaTelefonica createContaOIFixo(BufferedReader reader) throws Exception {

        ContaTelefonica contaTelefonica = new ContaTelefonica();

        contaTelefonica.contaMensal = new ArrayList<EntradaAbstrata>();
        String line = null;
        Telefone origem = null;
        boolean cobrar = false;
        String ddd = null;
        Pattern pattern = Pattern.compile("[0-9]+:[0-9]{2}");

        while ((line = reader.readLine()) != null) {

            line = line.trim();

            if (line.length() == 0) {
                continue;
            }

            if ((ddd == null) && line.startsWith("CODIGO DDD")) {
                line = reader.readLine().trim();
                ddd = line;
                continue;
            }


            if (origem == null) {
                String[] tokens = line.split(" ");
                String fone = tokens[0];
                Matcher m = QuebraStringOI.telefone.matcher(fone);

                if (m.find()) {
                    fone = m.group();
                    String num1 = fone.substring(0, 4);
                    String num2 = fone.substring(5);
                    origem = new Telefone(ddd, num1, num2);
                }

                continue;
            }

            if (line.startsWith("LIG") && line.contains("COBRAR")) {

                Matcher matcher = pattern.matcher(line);

                if (!matcher.find()) {
                    cobrar = true;
                }
                continue;
            }

            if (line.startsWith("SUBTOTAL")) {
                cobrar = false;
                continue;
            }

            String temp = line.split(" ")[0];

            //Se der erro é aqui!
            Matcher matchLig = Pattern.compile("([0-9]{4}[/][0-9]{2}|L[0-9]{6}?)").matcher(temp);

            if (matchLig.find()) {
                contaTelefonica.contaMensal.add(QuebraStringOI.quebraStringOIFixo(line, origem, cobrar));
            }



        }

        reader.close();

        Collections.sort(contaTelefonica.contaMensal, new ComparatorEntradaAbstrataPorTelefone());

        contaTelefonica.contaResumida();


        return contaTelefonica;
    }

    protected ContaTelefonica() {
    }

    public void contaResumida() {

        contaResumida = new ArrayList<LigacaoResumida>();
        ligacoes = new ArrayList<Ligacao>();

        for (EntradaAbstrata entrada : contaMensal) {
            if (entrada.isLigacao()) {
                ligacoes.add((Ligacao) entrada);
            }
        }

        contaResumida = getContasResumidas(ligacoes);

    }

    public static List<LigacaoResumida> getContasResumidas(List<Ligacao> ligacoes) {
        List<LigacaoResumida> contaResumida = new ArrayList<LigacaoResumida>();

        Collections.sort(ligacoes);

        Telefone origemAtual = null;
        Telefone destinoAtual = null;

        int tempoTotalAtual = 0;
        int numLigacoes = 0;
        double valorAtual = 0.0;
        boolean aCobrar = false;
        String tipoDeLigacaoAtual = "";

        for (Ligacao ligacao : ligacoes) {

            if (!ligacao.getNumeroDeOrigem().equals(origemAtual)) {

                if (origemAtual != null) {

                    LigacaoResumida ligacaoResumida = new LigacaoResumida(origemAtual, destinoAtual, valorAtual, numLigacoes,
                            tempoTotalAtual, tipoDeLigacaoAtual, aCobrar);

                    contaResumida.add(ligacaoResumida);

                }

                origemAtual = ligacao.getNumeroDeOrigem();
                destinoAtual = ligacao.getDestino();

                if (ligacao.isACobrar()) {
                    aCobrar = true;
                    tempoTotalAtual = ligacao.getDuracaoLigacaoACobrarSegundos();
                } else {
                    aCobrar = false;
                    tempoTotalAtual = ligacao.getDuracaoLigacaoSegundos();
                }

                tipoDeLigacaoAtual = ligacao.getTipoDeLigacao();
                valorAtual = ligacao.getCusto().doubleValue();
                numLigacoes = 1;

            } else if ((!ligacao.getDestino().equals(destinoAtual)) || (aCobrar ^ ligacao.isACobrar())
                    || (!ligacao.getTipoDeLigacao().equals(tipoDeLigacaoAtual))) {
                if (origemAtual != null) {
                    LigacaoResumida ligacaoResumida = new LigacaoResumida(origemAtual, destinoAtual, valorAtual, numLigacoes,
                            tempoTotalAtual, tipoDeLigacaoAtual, aCobrar);

                    contaResumida.add(ligacaoResumida);
                }
                destinoAtual = ligacao.getDestino();

                if (ligacao.isACobrar()) {
                    aCobrar = true;
                    tempoTotalAtual = ligacao.getDuracaoLigacaoACobrarSegundos();
                } else {
                    aCobrar = false;

                    tempoTotalAtual = ligacao.getDuracaoLigacaoSegundos();

                }

                tipoDeLigacaoAtual = ligacao.getTipoDeLigacao();
                valorAtual = ligacao.getCusto().doubleValue();
                numLigacoes = 1;

            } else {

                if (ligacao.isACobrar()) {
                    aCobrar = true;
                    tempoTotalAtual += ligacao.getDuracaoLigacaoACobrarSegundos();
                } else {
                    aCobrar = false;
                    tempoTotalAtual += ligacao.getDuracaoLigacaoSegundos();
                }

                valorAtual += ligacao.getCusto().doubleValue();
                numLigacoes++;
            }

        }
        if (origemAtual != null) {
            LigacaoResumida ligacaoResumida = new LigacaoResumida(origemAtual, destinoAtual, valorAtual, numLigacoes,
                    tempoTotalAtual, tipoDeLigacaoAtual, aCobrar);

            contaResumida.add(ligacaoResumida);

        }
        return contaResumida;
    }
}
